package com.zhj.user.service.impl;

import com.zhj.common.util.DateUtil;
import com.zhj.common.util.MD5Utils;
import com.zhj.common.util.id.Sid;
import com.zhj.user.config.WxConfig;
import com.zhj.user.entity.dto.UserDTO;
import com.zhj.user.entity.dto.UserRegisterDTO;
import com.zhj.user.entity.dto.WxLoginRequestDTO;
import com.zhj.user.entity.pojo.User;
import com.zhj.user.entity.vo.WxLoginResponseVO;
import com.zhj.user.enums.Sex;
import com.zhj.user.mapper.UserMapper;
import com.zhj.user.service.UserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.Date;
import java.util.Objects;

@Service
@Slf4j
@AllArgsConstructor
public class UserServiceImpl implements UserService {
    //默认头像地址
    private static final String USER_FACE = "http://122.152.205.72:88/group1/M00/00/05/CpoxxFw_8_qAIlFXAAAcIhVPdSg994.png";

    private final Sid sid;

    private final UserMapper userMapper;

    private final RestTemplate restTemplate;

    private final WxConfig wxConfig;


    @Override
    public User selectByPrimaryKey(String id) {
        return this.userMapper.selectById(id);
    }

    /**
     * 判断用户是否存在
     *
     * @param username
     * @return
     */
    @Override
    public boolean usernameIsExist(String username) {
        return this.userMapper.usernameIsExist(username);
    }

    /**
     * 创建用户信息
     *
     * @param userRegisterDTO
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public User createUser(UserRegisterDTO userRegisterDTO) {

        String confirmPassword = userRegisterDTO.getConfirmPassword();
        String password = userRegisterDTO.getPassword();
        if (!StringUtils.equals(confirmPassword, password)) {
            throw new RuntimeException("两次输入密码不相同");
        }
        User user = new User()
                .setUsername(userRegisterDTO.getUsername())
                .setId(sid.nextShort());
        try {
            user.setPassword(MD5Utils.getMD5Str(password));
        } catch (Exception e) {
            log.error("密码加密失败");
        }
        // 默认用户昵称同用户名
        user.setNickname(userRegisterDTO.getUsername())
                .setFace(USER_FACE)
                .setBirthday(DateUtil.stringToDate("1900-01-01"))
                .setSex(Sex.secret.type)
                .setCreatedTime(new Date())
                .setUpdatedTime(new Date());
        this.userMapper.insert(user);
        return user;
    }

    @Override
    public User login(UserDTO userDTO) {
        try {
            userDTO.setPassword(MD5Utils.getMD5Str(userDTO.getPassword()));
        } catch (Exception e) {
            log.error("密码解密失败");
        }
        return this.userMapper.login(userDTO);
    }

    /**
     * 微信登录实现
     * @param jsCode
     * @return
     */
    @Override
    public WxLoginResponseVO loginForWx(String jsCode) {
        WxLoginRequestDTO wxLoginRequestDTO = WxLoginRequestDTO.builder()
                .js_code(jsCode)
                .appid(wxConfig.getAppId())
                .secret(wxConfig.getAppSecret())
                .grant_type("authorization_code")
                .build();
        String url = wxConfig.getUrl();
        //拼接参数
        URI uri = UriComponentsBuilder.fromHttpUrl(url)
                .queryParam("appid", wxLoginRequestDTO.getAppid())
                .queryParam("secret", wxLoginRequestDTO.getSecret())
                .queryParam("js_code", wxLoginRequestDTO.getJs_code())
                .queryParam("grant_type", "authorization_code")
                .build().encode().toUri();
        log.info("微信登录地址：{}", uri);
        ResponseEntity<WxLoginResponseVO> wxLoginVOResponseEntity = this.restTemplate.getForEntity(uri, WxLoginResponseVO.class);
        HttpStatus statusCode = wxLoginVOResponseEntity.getStatusCode();
        WxLoginResponseVO wxLoginVOResponseEntityBody = Objects.requireNonNull(wxLoginVOResponseEntity.getBody(), "微信登录失败");
        if (HttpStatus.OK.equals(statusCode) && wxLoginVOResponseEntityBody.getErrcode() == 0) {
            //将获取到授权的微信 openApi 存入到数据库中
        } else {
            throw new RuntimeException("微信登录失败：" + wxLoginVOResponseEntityBody.getErrmsg());
        }
        return wxLoginVOResponseEntityBody;
    }

}
